﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using Project.Controller;

namespace Project.Model
{
    public class Speler : SpelerObserver, SpelerObservable
    {
        private string naam;
        private Color color;
        protected Pion[] pionnen;

        private int worp;

        public int Worp
        {
            get { return worp; }
            set { worp = value; }
        }

        private Vak[] vak_eind;
        private Vak vak_a;
        private Vak[] vak_b;

        private SpelObserver observer;

        public SpelObserver Observer
        {
            get { return observer; }
            set { observer = value; }
        }

        private Pion laatstePionVerplaats;

        public Speler(string naam, Color color)
        {
            this.naam = naam;
            this.color = color;
            pionnen = new Pion[4];
            pionnen[0] = new Pion(this.color);
            pionnen[1] = new Pion(this.color);
            pionnen[2] = new Pion(this.color);
            pionnen[3] = new Pion(this.color);
            pionnen[0].RegisterObserver(this);
            pionnen[1].RegisterObserver(this);
            pionnen[2].RegisterObserver(this);
            pionnen[3].RegisterObserver(this);

            vak_a = new Vak(VakType.Vak_A);

            vak_b = new Vak[4];
            vak_b[0] = new Vak(VakType.Vak_B);
            vak_b[1] = new Vak(VakType.Vak_B);
            vak_b[2] = new Vak(VakType.Vak_B);
            vak_b[3] = new Vak(VakType.Vak_B);

            vak_b[0].setPion(pionnen[0]);
            vak_b[1].setPion(pionnen[1]);
            vak_b[2].setPion(pionnen[2]);
            vak_b[3].setPion(pionnen[3]);

            vak_b[0].Next = vak_a;
            vak_b[1].Next = vak_a;
            vak_b[2].Next = vak_a;
            vak_b[3].Next = vak_a;

            vak_eind = new Vak[4];
            vak_eind[0] = new Vak(VakType.Vak_Eind);
            vak_eind[1] = new Vak(VakType.Vak_Eind);
            vak_eind[2] = new Vak(VakType.Vak_Eind);
            vak_eind[3] = new Vak(VakType.Vak_Eind);

            vak_eind[0].setNext(vak_eind[1]);
            vak_eind[1].setNext(vak_eind[2]);
            vak_eind[2].setNext(vak_eind[3]);
        }

        public void RegisterObserver(SpelObserver o)
        {
            this.observer = o;
        }

        public void Update()
        {
            for (int i = 0; i < this.pionnen.Count(); i++)
            {
                Pion pion = this.pionnen[i];
                if (pion.PionMoetTerug)
                {
                    this.SetPionTerug(pion);
                    this.observer.Trace("De pion van speler " + this.Naam + " is geslagen.");
                    pion.PionMoetTerug = false;
                }
            }
        }

        // Verplaats de pion
        // @param pion: De pion die moet worden verplaatst
        public void VerplaatsPion(Pion pion)
        {
            if (pion.Vak.VakType == VakType.Vak_B)
            {
                pion.Vak.Pion = null;
                pion.Vak = pion.Vak.Next;
                pion.Vak.setPion(pion);
                this.laatstePionVerplaats = pion;
                this.observer.Trace(this.naam + " verplaatst een pion.");
                this.resetPionnen();
                this.observer.PionVerzet(true);
            }
            else
            {
                pion.Vak.Pion = null;
                Vak nv = pion.Vak;
                bool backwards = false;
                for (int i = 0; i < this.worp; i++)
                {
                    if (backwards)
                    {
                        nv = nv.Prev;
                    }
                    else
                    {
                        if (nv.NextEind != null && this.isMijnEindvak(nv.NextEind))
                        {
                            nv = nv.NextEind;
                        }
                        else if (nv.Next == null)
                        {
                            nv = nv.Prev;
                            backwards = true;
                        }
                        else
                        {
                            nv = nv.Next;
                        }
                    }
                }
                nv.setPion(pion);
                this.laatstePionVerplaats = null;
                if (nv.VakType == VakType.Vak_Eind)
                {
                    this.observer.Trace(this.naam + "verplaatse een pion naar het eindvak.");
                }
                else
                {
                    this.observer.Trace(this.naam + " verplaatst een pion.");
                }
                this.resetPionnen();
                this.observer.PionVerzet(false);
            }
        }

        // Set Mogelijke Vakken
        public int setMogelijkeVakken(int worp)
        {
            this.resetPionnen();
            this.worp = worp;
            int count = 0;
            if (this.laatstePionVerplaats != null)
            {
                this.laatstePionVerplaats.Move = true;
                this.laatstePionVerplaats.PionPanel.addBorder();
                count++;
            }
            else
            {
                if (this.worp == 6)
                {
                    for (int i = 0; i < this.pionnen.Count(); i++)
                    {
                        if (!zijnBeginvakkenLeeg())
                        {
                            if (pionnen[i].Vak.VakType == VakType.Vak_B)
                            {
                                pionnen[i].Move = true;
                                pionnen[i].PionPanel.addBorder();
                                count++;
                            }
                        }
                        else
                        {
                            if (pionnen[i].Vak.VakType != VakType.Vak_Eind)
                            {
                                pionnen[i].Move = true;
                                pionnen[i].PionPanel.addBorder();
                                count++;
                            }
                        }
                    }
                }
                else
                {
                    for (int i = 0; i < this.pionnen.Count(); i++)
                    {
                        Vak nv = this.pionnen[i].Vak;
                        bool backwards = false;
                        if (nv.VakType == VakType.Vak_A || nv.VakType == VakType.Vak_Normaal)
                        {
                            for (int j = 0; j < this.worp; j++)
                            {
                                if (backwards)
                                {
                                    nv = nv.Prev;
                                }
                                else
                                {
                                    if (nv.NextEind != null && this.isMijnEindvak(nv.NextEind))
                                    {
                                        nv = nv.NextEind;
                                    }
                                    else if (nv.Next == null)
                                    {
                                        nv = nv.Prev;
                                        backwards = true;
                                    }
                                    else
                                    {
                                        nv = nv.Next;
                                    }
                                }
                            }
                            if (pionnen[i].Vak.VakType != VakType.Vak_B
                                && pionnen[i].Vak.VakType != VakType.Vak_Eind
                                && !(nv.VakType == VakType.Vak_Eind && nv.heeftPion()))
                            {
                                pionnen[i].Move = true;
                                pionnen[i].PionPanel.addBorder();
                                count++;
                            }
                        }
                    }
                }
            }
            return count;
        }

        // Maak alle pionnen weer de orginele kleur en disable dat ze verplaatst kunnen worden
        public void resetPionnen()
        {
            for (int i = 0; i < this.pionnen.Count(); i++)
            {
                this.pionnen[i].PionPanel.removeBorder();
                this.pionnen[i].Move = false;
            }
        }

        public void SetPionTerug(Pion pion)
        {
            for (int i = 0; i < 4; i++)
            {
                if (!this.vak_b[i].heeftPion())
                {
                    this.vak_b[i].setPion(pion);
                }
            }
        }

        public bool zijnBeginvakkenLeeg()
        {
            for (int i = 0; i < 4; i++)
            {
                if (this.vak_b[i].heeftPion())
                {
                    return false;
                }
            }
            return true;
        }

        // Pionnen Property
        public Pion[] Pionnen
        {
            get { return pionnen; }
            set { pionnen = value; }
        }

        // Vak_b Property
        public Vak[] Vak_b
        {
            get { return vak_b; }
            set { vak_b = value; }
        }

        // Vak_eind Property
        public Vak[] Vak_eind
        {
            get { return vak_eind; }
            set { vak_eind = value; }
        }

        // Vak_a Property
        public Vak Vak_a
        {
            get { return vak_a; }
            set { vak_a = value; }
        }

        // Naam Property
        public string Naam
        {
            get { return naam; }
            set { naam = value; }
        }

        // Color Property
        public Color Color
        {
            get { return color; }
            set { color = value; }
        }

        // LaatstePionVerplaats Property
        public Pion LaatstePionVerplaats
        {
            get { return laatstePionVerplaats; }
            set { laatstePionVerplaats = value; }
        }

        // Heeft de speler gewonnen?
        public bool isWinnaar()
        {
            for (int i = 0; i < this.Vak_eind.Count(); i++)
            {
                if (!this.vak_eind[i].heeftPion())
                {
                    return false;
                }
            }
            return true;
        }

        // Controleer of het gegeven vak 1 van mijn eindvakken is
        // @param vak: Eindvak dat moet worden gecontroleerd
        public bool isMijnEindvak(Vak vak)
        {
            for (int i = 0; i < this.Vak_eind.Count(); i++)
            {
                if (this.Vak_eind[i] == vak)
                {
                    return true;
                }
            }
            return false;
        }

    }
}
